﻿using System;
using System.ComponentModel.Composition;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using ASPItalia.ModelVirtualCasting.Common;
using ASPItalia.ModelVirtualCasting.EntityFramework.Wrappers;
using ASPItalia.ModelVirtualCasting.ObjectModel;
using ASPItalia.ModelVirtualCasting.Parts;

namespace ASPItalia.ModelVirtualCasting.EntityFramework
{
	[Export("ModelRepository", typeof(IModelRepository))]
	[PartCreationPolicy(CreationPolicy.NonShared)]
	[RepositoryMetadata(Name = "ModelRepository", IsFake = false)]
	public class ModelRepository : BaseRepository<Model>, IModelRepository
	{
		[ImportingConstructor()]
		public ModelRepository(IContextContainer container)
			: base(container)
		{
		}

		internal ModelRepository(IDbSet<Model> objectSet)
			: base(objectSet)
		{
		}

		public void InsertOnSubmit(Model entity)
		{
			throw new NotImplementedException();
		}

		public void Update(Model entity)
		{
			CurrentSet.Attach(entity);
			Context.ChangeObjectState(entity, EntityState.Modified);
		}

		public void DeleteOnSubmit(Model entity)
		{
			CurrentSet.Remove(entity);
		}

		public void SubmitChanges()
		{
			base.SaveChanges();
		}

		public IQueryable<ModelDTO> GetRandomModels(int number)
		{
			var query = (from m in CurrentQueryableSet.OfType<Model>()
									 select new ModelDTO
									 {
										 Age = DateTime.Today.Year - m.BirthDate.Year,
										 Country = m.ResidenceCountry.CountryName,
										 NickName = m.NickName,
										 ImageUrl = m.Multimedia.Where(image => image is Image).FirstOrDefault().FileName
									 }).OrderByRandom().Take(number).AsQueryable();

			// TODO OrderByRandom enumera la collection, considerare di usare la cache

			return query;
		}

		public IQueryable<Model> GetAll()
		{
			return CurrentQueryableSet.OfType<Model>();
		}

		public IQueryable<Model> Where(Expression<Func<Model, bool>> predicate)
		{
			return CurrentQueryableSet.OfType<Model>().Where(predicate);
		}

		public long Count(Expression<Func<Model, bool>> predicate)
		{
			return CurrentQueryableSet.OfType<Model>().Count(predicate);
		}

		public IModelRepository Include<TProperty>(Expression<Func<Model, TProperty>> path)
		{
			IncludeInternal(path);
			return this;
		}

		public IModelRepository Include(string path)
		{
			IncludeInternal(path);
			return this;
		}

		public IModelRepository CreateQuery()
		{
			CreateQueryInternal();
			return this;
		}

		public IModelRepository EnableLazyLoading()
		{
			SetLazyLoading(true);
			return this;
		}

		public IModelRepository DisableLazyLoading()
		{
			SetLazyLoading(false);
			return this;
		}

		public IModelRepository DoNotTrack()
		{
			base.DoNotTrackInternal();
			return this;
		}
	}
}